const DEST_TABLE = {
  null: '000',
  M: '001',
  D: '010',
  DM: '011',
  MD: '011',
  A: '100',
  AM: '101',
  MA: '101',
  AD: '110',
  DA: '110',
  ADM: '111',
  AMD: '111',
  MDA: '111',
  MAD: '111',
  DMA: '111',
  DAM: '111'
};

const JUMP_TABLE = {
  null: '000',
  JGT: '001',
  JEQ: '010',
  JGE: '011',
  JLT: '100',
  JNE: '101',
  JLE: '110',
  JMP: '111'
};

const COMP_TABLE = {
  0: { prefix: '0', control: '101010' },
  1: { prefix: '0', control: '111111' },
  '-1': { prefix: '0', control: '111010' },
  D: { prefix: '0', control: '001100' },
  A: { prefix: '0', control: '110000' },
  M: { prefix: '1', control: '110000' },
  '!D': { prefix: '0', control: '001101' },
  '!A': { prefix: '0', control: '110001' },
  '!M': { prefix: '1', control: '110001' },
  '-D': { prefix: '0', control: '001111' },
  '-A': { prefix: '0', control: '110011' },
  '-M': { prefix: '1', control: '110011' },
  'D+1': { prefix: '0', control: '011111' },
  'A+1': { prefix: '0', control: '110111' },
  'M+1': { prefix: '1', control: '110111' },
  'D-1': { prefix: '0', control: '001110' },
  'A-1': { prefix: '0', control: '110010' },
  'M-1': { prefix: '1', control: '110010' },
  'D+A': { prefix: '0', control: '000010' },
  'D+M': { prefix: '1', control: '000010' },
  'D-A': { prefix: '0', control: '010011' },
  'D-M': { prefix: '1', control: '010011' },
  'A-D': { prefix: '0', control: '000111' },
  'M-D': { prefix: '1', control: '000111' },
  'D&A': { prefix: '0', control: '000000' },
  'D&M': { prefix: '1', control: '000000' },
  'D|A': { prefix: '0', control: '010101' },
  'D|M': { prefix: '1', control: '010101' }
};

class Code {
  dest(destToken) {
    return DEST_TABLE[destToken];
  }

  comp(compToken) {
    const target = COMP_TABLE[compToken];
    return target.prefix + target.control;
  }

  jump(jumpToken) {
    return JUMP_TABLE[jumpToken];
  }
}

module.exports.Code = Code;
